package com.jie.client.service.ui.view;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.jie.client.core.ClientApplication;
import com.jie.client.core.handler.ClientWriteHandler;
import com.jie.client.service.entity.model.User;
import com.jie.client.service.ui.constant.ViewMapConstant;
import com.jie.client.service.ui.model.OnlineListNode;
import com.jie.client.service.ui.model.SetNode;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 主页面
 * @author XieZhiJie
 * @date 2022/04/27 16:22
 */
public class MainView {

    private final Logger logger = LoggerFactory.getLogger(MainView.class);

    /**
     * 当前用户信息
     */
    private User user;

    /**
     * 在线用户列表视图
     */
    private final ListView<String> onlineListView = new ListView<>();

    /**
     * 在线用户详细信息
     */
    private final List<User> onlineListDetailsData = new LinkedList<>();

    /**
     * 在线用户列表数据项, 记录 用户名(用户账号)
     */
    private final ObservableList<String> onlineListData = FXCollections.observableArrayList();

    /**
     * 存放和当前用户已存在的私聊页面的集合
     * value是其它用户的id
     */
    private final Set<Integer> singleChatSet = new ConcurrentHashSet<>(16);

    /**
     * 存放已经打开了的群聊列表id
     */
    private final Set<Integer> groupChatSet = new ConcurrentHashSet<>(16);

    /**
     * 获取主视图
     * @param user 需要传入当前用户的信息
     * @return     返回主视图
     */
    public Scene getMainView(User user) {
        this.user = user;
        ClientApplication.VIEW_MAP.put(ViewMapConstant.SINGLE_CHAT_SET, new SetNode(this.singleChatSet));
        ClientApplication.VIEW_MAP.put(ViewMapConstant.GROUP_CHAT_SET, new SetNode(this.groupChatSet));
        // 总界面
        GridPane root = new GridPane();

        // 用户信息
        GridPane userMessagePane = getUserMassagePane();

        // 在线列表
        GridPane onlineListPane = getOnlinePane();

        // 其它功能
        // 把其它功能放到在线列表下面
        Pane functionPane = getFunctionPane();
        onlineListPane.add(functionPane, 0, 2);

        // 添加Pane
        // 设置用户信息的位置
        root.add(userMessagePane, 0, 0);
        // 把在线列表放到root中
        root.add(onlineListPane, 0, 1);

        // 设置root的边距
        root.setPadding(new Insets(10, 10, 10, 36));

        return new Scene(root, 388, 688);
    }

    /**
     * 获取用户信息栏板
     * @return 返回用户信息栏板
     */
    private GridPane getUserMassagePane() {
        GridPane userMessagePane = new GridPane();
        Text u = new Text("\t用户信息");
        Text userIdText = new Text("用户id");
        Text userAccountText = new Text("用户帐号");
        Text usernameText = new Text("用户名");
        TextField userIdMessage = new TextField(this.user.getUserId());
        TextField userAccountMessage = new TextField(this.user.getUserAccount());
        TextField usernameMsg = new TextField(this.user.getUsername());

        // 设置用户信息栏不可更改
        userIdMessage.setEditable(false);
        userAccountMessage.setEditable(false);
        usernameMsg.setEditable(false);

        // 设置用户信息的布局
        userMessagePane.add(u, 1, 0);
        userMessagePane.add(userIdText, 0, 1);
        userMessagePane.add(userAccountText, 0, 2);
        userMessagePane.add(usernameText, 0, 3);
        userMessagePane.add(userIdMessage, 1, 1);
        userMessagePane.add(userAccountMessage, 1, 2);
        userMessagePane.add(usernameMsg, 1, 3);

        // 设置子控件的位置
        userMessagePane.setVgap(10);
        userMessagePane.setHgap(10);
        userMessagePane.setPadding(new Insets(10, 0, 0, 0));
        return userMessagePane;
    }

    /**
     * 获取在线用户列表pane
     * @return 返回在线用户列表pane
     */
    private GridPane getOnlinePane() {
        GridPane onlineListPane = new GridPane();
        onlineListPane.add(new Text("\t\t在线用户(双击私聊)"), 0, 0);
        onlineListPane.add(this.onlineListView, 0, 1);

        // 设置列表高度
        this.onlineListView.setPrefHeight(500);

        // 设置子控件的位置
        // 设置控件间的间距(我也不太会设置, 设置了这个比之前好看一些)
        onlineListPane.setVgap(10);
        onlineListPane.setHgap(10);
        onlineListPane.setPadding(new Insets(10, 0, 0, 0));

        // 对列表中的表项添加事件(鼠标双击弹出私聊窗口)
        this.onlineListView.setOnMouseClicked(this::onSingleChatAction);

        // 添加在线用户结点, 给响应填充数据
        OnlineListNode onlineListNode = new OnlineListNode(this.onlineListView, this.onlineListDetailsData, this.onlineListData);
        ClientApplication.VIEW_MAP.put(ViewMapConstant.ONLINE_LIST_NODE, onlineListNode);
        return onlineListPane;
    }

    /**
     * 获取其他功能的栏板
     * @return 返回其它功能的栏板
     */
    private Pane getFunctionPane() {
        // 刷新用户列表, 关注列表, 群聊列表的按钮
        Button followButton = new Button("关注列表");
        Button groupChatButton = new Button("群聊列表");
        Button flushOnlineUserListButton = new Button("刷新用户列表");

        HBox functionBox = new HBox();

        // 把按钮添加进functionBox中
        functionBox.getChildren().add(followButton);
        functionBox.getChildren().add(groupChatButton);
        functionBox.getChildren().add(flushOnlineUserListButton);

        // 给按钮设置事件
        followButton.setOnAction(event -> onOpenFollowListAction());
        groupChatButton.setOnAction(event -> onOpenGroupListAction());
        flushOnlineUserListButton.setOnAction(event -> onFlushOnlineUserListAction());

        functionBox.setSpacing(20);

        return functionBox;
    }

    /**
     * 鼠标双击在线用户事件, 触发私聊
     * @param event 事件
     */
    private void onSingleChatAction(MouseEvent event) {
        if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) {
            // PRIMARY:鼠标左键 ClickCount:2 == 双击
            // 哪一项被选中
            int index = this.onlineListView.getSelectionModel().getSelectedIndex();
            User choiceUser;
            try {
                // 不在线先不考虑
                choiceUser = this.onlineListDetailsData.get(index);
                if (choiceUser == null) {
                    return;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                logger.info("点击空白内容了...");
                return;
            }

            // 点到自己了
            if (Objects.equals(this.user.getUserId(), choiceUser.getUserId())) {
                return;
            }

            if (this.singleChatSet.contains(Integer.parseInt(choiceUser.getUserId()))) {
                logger.warn("已存在的私聊...");
                return;
            }
            // 添加和谁的群聊, 防止用户多次打开和某个用户的群聊窗口
            this.singleChatSet.add(Integer.parseInt(choiceUser.getUserId()));
            new SingleChatView(this.user, choiceUser, this.singleChatSet).createSingleChatView();
        }
    }

    /**
     * 刷新好友列表
     */
    private void onFlushOnlineUserListAction() {
        // 获取在线用户
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getOnlineUserList");
        ClientWriteHandler.sendRequest(map);
    }

    /**
     * 打开关注列表
     */
    private void onOpenFollowListAction() {
        if (ClientApplication.VIEW_MAP.containsKey(ViewMapConstant.FOLLOW_VIEW)) {
            return;
        }
        new FollowView().createFollowView();
        // 发送请求
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getFollowUserList");
        ClientWriteHandler.sendRequest(map);
    }

    /**
     * 打开群聊列表
     */
    private void onOpenGroupListAction() {
        if (ClientApplication.VIEW_MAP.containsKey(ViewMapConstant.GROUP_LIST_VIEW)) {
            return;
        }
        new GroupListView().createGroupListView();
        Map<String, Object> map = new HashMap<>(2);
        map.put("choice", "getUserGroupList");
        ClientWriteHandler.sendRequest(map);
    }

}
